import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import cloneDeep from 'lodash.clonedeep'
import { nanoid } from 'nanoid'
import { arrayMove } from '@dnd-kit/sortable'
import { ComponentPropsType } from '../../components/QuestionComponents/index'
import { produce } from 'immer'
import { getNextSelectedId, insertComponent } from './utils'
export type ComponentInfoType = {
  fe_id: string
  type: string
  title: string
  isHidden?: boolean
  isLocked?: boolean
  props: ComponentPropsType
}
export type ComponentStateType = {
  componetnList: Array<ComponentInfoType> // 存储所有的组件信息列表，列表中的每一个元素都是
  selectedId: string // 选择的组件的id值，用于区分不同的组件类型或组件id值，默认为
  copiedComponent: ComponentInfoType | null // 存储复制的组件信息，用于区分复制和选择的组件类型或组件id值
}
const INIT_STATE: ComponentStateType = {
  componetnList: [],
  selectedId: '',
  copiedComponent: null,
} // 初始化状态 （这样就可以将整个页
export const componentsSlice = createSlice({
  name: 'components',
  initialState: INIT_STATE,
  reducers: {
    //重置所有组件
    resetComponents: (state: ComponentStateType, actions: PayloadAction<ComponentStateType>) => {
      return actions.payload
    },
    //修改 sleectedId
    changeSleectedId: produce((draft: ComponentStateType, actions: PayloadAction<string>) => {
      draft.selectedId = actions.payload
    }),
    //添加新组件
    addComponnet: produce(
      (draft: ComponentStateType, actions: PayloadAction<ComponentInfoType>) => {
        const newComponent = actions.payload
        insertComponent(draft, newComponent)
      }
    ),
    // 修改组件属性
    changeComponentProps: produce(
      (
        draft: ComponentStateType,
        actions: PayloadAction<{ fe_id: string; newProps: ComponentPropsType }>
      ) => {
        const { fe_id, newProps } = actions.payload
        const curComp = draft.componetnList.find((item: any) => item.fe_id == fe_id) //找到要更新的组件
        if (curComp) {
          curComp.props = { ...curComp, ...newProps }
        }
      }
    ),
    // 删除选中的组件
    removeSelectedComponent: produce((draft: ComponentStateType) => {
      const { componetnList, selectedId } = draft
      const index = componetnList.findIndex((item: any) => item.fe_id == selectedId) //创建
      const newSeltctedId = getNextSelectedId(selectedId, componetnList)
      draft.selectedId = newSeltctedId
      componetnList.splice(index, 1)
    }),
    // 隐藏和显示组件
    changeComponentHidden: produce(
      (draft: ComponentStateType, actions: PayloadAction<{ fe_id: string; isHidden: boolean }>) => {
        const { componetnList } = draft
        const { fe_id, isHidden } = actions.payload
        let newSeltctedId = ''
        if (isHidden) {
          //如果是隐藏的组件
          newSeltctedId = getNextSelectedId(fe_id, componetnList)
        } else {
          // 要显示
          newSeltctedId = fe_id
        }

        draft.selectedId = newSeltctedId
        const curComp = componetnList.find(item => item.fe_id == fe_id) //找到要更新
        if (curComp) {
          curComp.isHidden = isHidden
        }
      }
    ),
    //锁定解锁组件或选中组件的选择区域，
    toggleComponentLock: produce(
      (draft: ComponentStateType, actions: PayloadAction<{ fe_id: string }>) => {
        // 方法一
        const { componetnList } = draft
        const { fe_id } = actions.payload
        const curComp = componetnList.find(item => item.fe_id == fe_id) //找到要更新
        if (curComp) {
          curComp.isLocked = !curComp.isLocked //将选中的组件的isLocked变为!curComp.isLocked
        }
        // 方法一二
        //  const { componetnList,selectedId } = draft
        // const index=componetnList.findIndex(item=>item.fe_id==selectedId) //找到要更新的
        // draft.componetnList[index].isLocked=!componetnList[index].isLocked //将选中的组件的isLocked变成不
      }
    ),
    // 拷贝当前组件
    copySelectedCompoent: produce((draft: ComponentStateType) => {
      const { componetnList, selectedId } = draft
      const curComp = componetnList.find(item => item.fe_id == selectedId)
      if (!curComp) return
      draft.copiedComponent = cloneDeep(curComp)
    }),
    //粘贴组件
    pasteSelectedCompoent: produce((draft: ComponentStateType) => {
      const { copiedComponent, componetnList, selectedId } = draft
      if (!copiedComponent) return
      copiedComponent.fe_id = nanoid() //id生成器生成一个随机的字符串作为id生成器的参数，这样copySelectedComp
      // 插入组件
      insertComponent(draft, copiedComponent)
    }),
    //选中上一个
    selectedPrevCompoent: (draft: ComponentStateType) => {
      const { componetnList, selectedId } = draft
      const selectedIndex = componetnList.findIndex(item => item.fe_id == selectedId) //找到选中的组件的位置
      if (selectedIndex < 0) return //未选中组件
      if (selectedIndex <= 0) return //选中的组件是第一个
      draft.selectedId = componetnList[selectedIndex - 1].fe_id //选中上一个组件的id变成上一个
    },
    //选择下一个
    selectedNextCompoent: (draft: ComponentStateType) => {
      const { componetnList, selectedId } = draft
      const selectedIndex = componetnList.findIndex(item => item.fe_id == selectedId) //找到选中的组件的位置
      if (selectedIndex < 0) return //未选中组件
      if (selectedIndex == componetnList.length - 1) return //选中的组件是最后一个
      draft.selectedId = componetnList[selectedIndex + 1].fe_id //选中下一个组件的id变成下一个 （这样
    },
    //修改组件标题
    changeCompoentTitle: produce(
      (draft: ComponentStateType, actions: PayloadAction<{ fe_id: string; title: string }>) => {
        const { title, fe_id } = actions.payload
        const curComp = draft.componetnList.find(c => c.fe_id === fe_id)
        if (curComp) curComp.title = title //把选中的组件的title变成你要修改的值
      }
    ),
    //移动组件位置 拖拽
    moveCompoent: produce(
      (
        draft: ComponentStateType,
        actions: PayloadAction<{ oldIndex: number; newIndex: number }>
      ) => {
        const { componetnList: curCompList } = draft
        const { oldIndex, newIndex } = actions.payload
        draft.componetnList = arrayMove(curCompList, oldIndex, newIndex)
      }
    ),
  },
})
export const {
  resetComponents,
  changeSleectedId,
  addComponnet,
  changeComponentProps,
  removeSelectedComponent,
  changeComponentHidden,
  toggleComponentLock,
  copySelectedCompoent,
  pasteSelectedCompoent,
  selectedPrevCompoent,
  selectedNextCompoent,
  changeCompoentTitle,
  moveCompoent,
} = componentsSlice.actions
export default componentsSlice.reducer
